package fun.easycode.webterminal.adapter.socket;

import cn.hutool.extra.ssh.ChannelType;
import com.jcraft.jsch.ChannelShell;
import fun.easycode.webterminal.common.jsch.JschJumpSession;
import lombok.SneakyThrows;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ThreadPoolExecutor;

public class Terminal {

    private final String machineId;
    private final WebSocketSession socketSession;
    private final ThreadPoolExecutor executor;

    private JschJumpSession jschJumpSession;

    private ChannelShell channel;
    private OutputStream outputStream;
    private InputStream inputStream;


    public Terminal(String machineId, WebSocketSession socketSession, ThreadPoolExecutor executor){

        this.machineId = machineId;
        this.socketSession = socketSession;
        this.executor = executor;
    }

    @SneakyThrows
    public void connect() {


        this.jschJumpSession = new JschJumpSession(machineId);
        this.jschJumpSession.connect();


        this.channel = (ChannelShell) this.jschJumpSession.getSession().openChannel(ChannelType.SHELL.getValue());
        this.channel.setPty(true);

        this.outputStream = this.channel.getOutputStream();
        this.inputStream = this.channel.getInputStream();

        this.channel.connect();

        executor.submit(() -> {
            try {
                byte[] buffer = new byte[1024];
                int read;
                while ((read = inputStream.read(buffer)) != -1) {
                    String output = new String(buffer, 0, read, StandardCharsets.UTF_8);
//                    System.err.println("output => " + output);
                    this.socketSession.sendMessage(new TextMessage(output));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

    }

    public void disconnect(){
        if(this.channel != null){
            this.channel.disconnect();
        }
        if(this.jschJumpSession != null){
            this.jschJumpSession.disconnect();
        }
    }

    @SneakyThrows
    public void send(MessageContent content){
        if (content.getType() == MessageContentType.Forward) {
            this.outputStream.write(content.getContent().getBytes(StandardCharsets.UTF_8));
            this.outputStream.flush();
        }else if (content.getType() == MessageContentType.Resize){

            Integer cols = (Integer) content.getParams().get("cols");
            Integer rows = (Integer) content.getParams().get("rows");

            this.channel.setPty(true);
            this.channel.setPtySize(cols, rows, 0, 0);
        }else{
            this.socketSession.sendMessage(new TextMessage("ERROR：未知的消息类型。"));
        }
    }

    @SneakyThrows
    public void send(byte[] content){
        this.outputStream.write(content);
        this.outputStream.flush();
    }

}
